from rest_framework.generics import GenericAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView, get_object_or_404
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet, ReadOnlyModelViewSet, ModelViewSet

from books.models import BookInfo
from books.serializer import BookModelSerializer
from rest_framework.mixins import *


class BooksListAPIView(APIView):
    def get(self, request):
        """get all books"""
        books = BookInfo.objects.all()

        serializer = BookModelSerializer(instance=books, many=True)

        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request):
        """create a new book object"""
        # book_data = request.data
        book_data = request.query_params
        serializer = BookModelSerializer(data=book_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)


class BooksDetailAPIView(APIView):

    def get(self, request, book_id):
        """get one object"""
        try:
            book = BookInfo.objects.get(id=book_id)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

        serializer = BookModelSerializer(instance=book)

        return Response(serializer.data, status=200)

    def put(self, request, book_id):
        """modify book information"""
        try:
            book = BookInfo.objects.get(id=book_id)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

        book_data = request.data

        serializer = BookModelSerializer(instance=book, data=book_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self, request, book_id):
        """delete a book"""
        try:
            BookInfo.objects.get(id=book_id).delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)


class BooksListGenericView(GenericAPIView):

    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer

    def get(self, request):
        """get all books"""
        books = self.get_queryset()

        # serializer = self.get_serializer(instance=books, many=True)
        serializer = self.get_serializer_class()(instance=books, many=True)
        # serializer = self.serializer_class(instance=books, many=True)

        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request):
        """create a new book object"""
        book_data = request.data
        # book_data = request.query_params
        serializer = self.serializer_class(data=book_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)


class BooksDetailGenericView(GenericAPIView):

    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer
    lookup_url_kwarg = 'book_id'

    def get(self, request, book_id):
        """get one object"""

        book = self.get_object()

        serializer = self.serializer_class(instance=book)

        return Response(serializer.data, status=200)

    def put(self, request, book_id):
        """modify book information"""

        book = self.get_object()

        book_data = request.data

        serializer = self.get_serializer(instance=book, data=book_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self, request, book_id):
        """delete a book"""
        try:
            self.get_object().delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)


class BookListMixinView(GenericAPIView, CreateModelMixin, ListModelMixin):

    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer

    def get(self, request):
        """get all books"""
        # books = self.get_queryset()
        #
        # # serializer = self.get_serializer(instance=books, many=True)
        # serializer = self.get_serializer_class()(instance=books, many=True)
        # # serializer = self.serializer_class(instance=books, many=True)
        #
        # return Response(serializer.data, status=status.HTTP_200_OK)
        return self.list(request)

    def post(self, request):
        """create a new book object"""
        # book_data = request.data
        # # book_data = request.query_params
        # serializer = self.serializer_class(data=book_data)
        # serializer.is_valid(raise_exception=True)
        # serializer.save()
        #
        # return Response(serializer.data, status=status.HTTP_201_CREATED)
        return self.create(request)


class BookDetailMixinView(GenericAPIView, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin):

    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer
    lookup_url_kwarg = 'book_id'

    def get(self, request, book_id):
        """get one object"""

        # book = self.get_object()
        #
        # serializer = self.serializer_class(instance=book)
        #
        # return Response(serializer.data, status=200)
        return self.retrieve(request)

    def put(self, request, book_id):
        """modify book information"""

        # book = self.get_object()
        #
        # book_data = request.data
        #
        # serializer = self.get_serializer(instance=book, data=book_data)
        # serializer.is_valid(raise_exception=True)
        # serializer.save()
        #
        # return Response(serializer.data, status=status.HTTP_201_CREATED)
        return self.update(request)

    def delete(self, request, book_id):
        """delete a book"""
        # try:
        #     self.get_object().delete()
        #     return Response(status=status.HTTP_204_NO_CONTENT)
        # except:
        #     return Response(status=status.HTTP_404_NOT_FOUND)
        return self.destroy(request)


class BookListThirdView(ListCreateAPIView):

    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer


class BookDetailThirdView(RetrieveUpdateDestroyAPIView):

    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer
    lookup_url_kwarg = 'book_id'


class BookGetViewSet(ViewSet):

    def list(self, request):
        """get all books"""
        books = BookInfo.objects.all()

        serializer = BookModelSerializer(instance=books, many=True)

        return Response(serializer.data, status=status.HTTP_200_OK)

    def retrieve(self, request, book_id):
        """get one object"""
        queryset = BookInfo.objects.all()
        book = get_object_or_404(queryset, pk=book_id)
        serializer = BookModelSerializer(instance=book)

        return Response(serializer.data, status=200)


class BookReadOnlyViewSet(ReadOnlyModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer
    lookup_url_kwarg = 'book_id'


class BookModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer

    def filter_bread(self, request):
        books = self.queryset.filter(bread__gte=20)
        serializer = self.get_serializer(instance=books, many=True)

        return Response(serializer.data)

    def update_bread(self, request, pk):

        book = self.get_object()
        data = request.data
        serializer = self.get_serializer(instance=book, data=data, partial=True)

        serializer.is_valid()
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
